package com.example.websocket.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@ServerEndpoint("/ws/lineChart/{deviceId}") // 添加设备ID路径参数
@Component
public class WebSocketEndpoint {
    // 用设备ID作为key存储会话，方便按设备发送消息
    private static final Map<String, Session> deviceSessions = new ConcurrentHashMap<>();
    // 存储会话ID与设备ID的映射，用于关闭连接时清理
    private static final Map<String, String> sessionDeviceMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("deviceId") String deviceId) { // 接收设备ID参数
        // 存储会话关联关系
        deviceSessions.put(deviceId, session);
        sessionDeviceMap.put(session.getId(), deviceId);

        // 首次连接发送初始数据
        sendInitialData(session, deviceId);
    }

    @OnClose
    public void onClose(Session session) {
        // 根据会话ID获取设备ID并清理映射关系
        String deviceId = sessionDeviceMap.get(session.getId());
        if (deviceId != null) {
            deviceSessions.remove(deviceId);
        }
        sessionDeviceMap.remove(session.getId());
    }

    /**
     * 定时向指定设备发送数据
     * @param session 会话
     * @param deviceId 设备ID
     */
    private void sendInitialData(Session session, String deviceId) {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        // 每2秒推送一次
        scheduler.scheduleAtFixedRate(() -> {
            try {
                // 生成当前设备的随机数据
                WeldingData data = generateRandomData(deviceId);
                // 只向当前设备会话发送数据
                session.getBasicRemote().sendText(new ObjectMapper().writeValueAsString(data));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 0, 2, TimeUnit.SECONDS);
    }

    /**
     * 生成包含设备ID的随机数据
     * @param deviceId 设备ID
     */
    private WeldingData generateRandomData(String deviceId) {
        String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        double current = 150 + Math.random() * 300;
        double voltage = 15 + Math.random() * 30;

        return new WeldingData(
                deviceId, // 添加上设备ID
                now,
                BigDecimal.valueOf(current).setScale(2, RoundingMode.HALF_UP).doubleValue(),
                BigDecimal.valueOf(voltage).setScale(2, RoundingMode.HALF_UP).doubleValue()
        );
    }

    /**
     * 向指定设备发送消息的工具方法
     * @param deviceId 设备ID
     * @param message 消息内容
     */
    public static void sendMessageToDevice(String deviceId, String message) {
        Session session = deviceSessions.get(deviceId);
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
